#include "common.h"
#include "dictionary.h"

Dictionary::Dictionary() {
	/* nothing to do :) */
}
Dictionary::~Dictionary() {
}

void Dictionary::add_duplicate(generic_object * src) {
	T("Dict:add_duplicate")
	int i; generic_object * ptr; map<double, generic_data>::iterator iternum; map<string, generic_data, ltstr_stl>::iterator iterstring;
	vector< generic_object* >::iterator iternest;

	if(!src) return; /* NULL cannot be duplicated ! */
	if(repository.find(src->name) != repository.end()) return; /* already have it/attempt to duplicate will not let this happen */

	ptr = new generic_object;
	if(!ptr) return;
	repository[src->name] = *ptr;
	for(iternum = src->numStore.begin(); iternum != src->numStore.end(); ++iternum) 
		ptr->numStore[iternum->first] = iternum->second;
	for(iterstring = src->stringStore.begin(); iterstring != src->stringStore.end(); ++iterstring) 
		ptr->stringStore[iterstring->first] = iterstring->second;
	for(iternest = src->nest.begin(); iternest != src->nest.end();++iternest)
		add_duplicate(*iternest); /* add recursively */
}

int Dictionary::LUA_get(lua_State *L) {
	T("Dict:LUA_get")
	map< string, generic_object ,ltstr_stl>::iterator tempiter; 
	map< double, generic_data, ltstr_stl >::iterator   tempiter_num; 
	map< string, generic_data, ltstr_stl >::iterator   tempiter_string;
	generic_object *ptr; generic_data* dataptr;

	if(!lua_isstring(L,ARG2_1)) return 0; /* imples a nil( nothing ) value is returned in lua */
	string object_name = string(lua_tostring(L,ARG2_1)); /* object name */

	tempiter = repository.find( object_name ); 
	if( tempiter == repository.end() ) return 0;
	ptr = & tempiter->second;
	if(lua_isnumber(L,ARG2_2)) { /* key is numeric */
		double key = lua_tonumber(L,ARG2_2);
		tempiter_num = ptr->numStore.find( key );
		if( tempiter_num == ptr->numStore.end() ) return 0;
		
		dataptr = & (tempiter_num->second);
		if(dataptr->isNumber) lua_pushnumber(L, dataptr->store.fData); else lua_pushstring(L,dataptr->store.sData.c_str());
		lua_pushnumber(L,1); 	return 1; /* signal success */
	}else { /* key is string */
		string key = lua_tostring(L,ARG2_2); cout << "key" << key << endl;
		tempiter_string = ptr->stringStore.find( key );
		if( tempiter_string == ptr->stringStore.end() ) return 0;

		dataptr = & tempiter_string->second;
		if(dataptr->isNumber) lua_pushnumber(L, dataptr->store.fData); else lua_pushstring(L,dataptr->store.sData.c_str());
		lua_pushnumber(L,1); 	return 1; /* signal success */
	}
	return 0; /* should never have reached here */
		
}

int Dictionary::LUA_set(lua_State *L) {
	T("Dict:LUA_set")
	map< string, generic_object ,ltstr_stl>::iterator tempiter; 
	map< double, generic_data, ltstr_stl >::iterator   tempiter_num; 
	map< string, generic_data, ltstr_stl >::iterator   tempiter_string;
	generic_object *ptr; generic_data datastore;

	if(!lua_isstring(L,ARG3_1)) return 0;
	string object_name = string(lua_tostring(L,ARG3_1)); /* object name */

	tempiter = repository.find( object_name );
	if( tempiter == repository.end() ) return 0;
	ptr = & tempiter->second;
	if(lua_isnumber(L,ARG3_2)) { /* key is numeric */
		M("key is numeric")
		double key = lua_tonumber(L,ARG3_2); 			M("key=" << key)
		datastore.isNumber = lua_isnumber(L,ARG3_3);	M("val is number ?" << (datastore.isNumber?"YES":"NO"))
		if(datastore.isNumber) datastore.store.fData = lua_tonumber(L,ARG3_3); else datastore.store.sData = lua_tostring(L,ARG3_3);
		ptr->numStore[ key ] = datastore;
		lua_pushnumber(L,1); 	return 1; /* signal success */
	}else { /* key is string */
		if(!lua_isstring(L,ARG3_3)) { E("Invalid key value specified. Must be a string/Number. String was expected since input was not a number") return 0; }
		M("key is string")
		string key = lua_tostring(L,ARG3_2);			M("key=" << key)
		datastore.isNumber = lua_isnumber(L,ARG3_3);	M("val is number ?" << (datastore.isNumber?"YES":"NO"))
		if(datastore.isNumber) datastore.store.fData = lua_tonumber(L,ARG3_3); else datastore.store.sData = lua_tostring(L,ARG3_3);
		ptr->stringStore[ key ] = datastore;
		lua_pushnumber(L,1); return 1; /* signal success */
	}
	return 0; /* should never reach here */

}

